#include "base/string_util.h"
#include <algorithm>
#include <cstdarg>
#include <ctime>
#include <cstring>

std::string& Trimmed(std::string &str) {
  if (str.empty()) return str;

  str.erase(0, str.find_first_not_of(" "));
  str.erase(str.find_last_not_of(" ") + 1);

  return str;
}

std::string Format(char const* format, ...) {
  std::vector<char> m_buffer;

  char const * str = 0;
  int ret = 0;
  va_list args;

  do {
    va_start(args, format);

    int printed;
    std::size_t const fmt_len = std::char_traits<char>::length(format);
    std::size_t buf_size = m_buffer.size();
    std::size_t const output_estimate = fmt_len + fmt_len / 2 + 1;
    if (output_estimate > buf_size)
      m_buffer.resize(buf_size = output_estimate);

    printed = vsnprintf(&m_buffer[0], buf_size, format, args);

    if (printed == -1) {
      buf_size *= 2;
      m_buffer.resize(buf_size);
    } else if (printed >= static_cast<int>(buf_size - 1)) {
      buf_size = printed + 2;
      m_buffer.resize(buf_size);
      printed = -1;
    } else {
      m_buffer[printed] = 0;
    }

    str = &m_buffer[0];
    ret = printed;

    va_end(args);
  } while (ret == -1);

  return str;
}

std::vector<std::string> Split(const std::string &str,
                               const std::string &delim) {
  std::vector<std::string> result;

  std::string strDest = str;
  char *token = NULL;
  token = strtok(const_cast<char*>(strDest.c_str()), delim.c_str());
  while (token != NULL) {
    result.push_back(token);
    token = strtok(NULL, delim.c_str());
  }

  return result;
}

std::string ToLower(const std::string &str) {
  std::string temp = str;
  transform(temp.begin(), temp.end(), temp.begin(), tolower);
  return temp;
}

std::string ToUpper(const std::string &str) {
  std::string temp = str;
  transform(temp.begin(), temp.end(), temp.begin(), toupper);
  return temp;
}

std::string RandomString(std::size_t size, const char* chars) {
  std::string result;
  int chars_len = strlen(chars);
  for (std::size_t i = 0; i < size; i++) {
    result.push_back(chars[rand() % chars_len]);
  }
  return result;
}
